jest tips
#jest #tips
モックがわからんなら一旦以下を読んでみる
jest mock
非同期処理が絡むテストを行う場合は、非同期の挙動に気をつけながらexpectを使え
SUTが非同期関数の場合、非同期関数内の処理が全て完了する前にexpect実行されちゃう可能性がある。
非同期関数内では、awaitをいい感じに使って、手続き的にしっかり処理を完了させることを意識しよう。
非同期関数内でthen, catchのチェーンを作るのはやめた方がいい。なんかテストがうまくいかない。
code: ng.js
async function sampleNgAsync() {
asyncFuncA().then((v) => {
asyncFuncB();
}).catch(err => {...});
};
code: ok.js
async function sampleOkAsync() {
try {
await asyncFuncA();
await asyncFuncB();
} catch (err) {
...
}
};
テストコードでもasync, awaitを意識する。
code: test.js
test("sample", async () => {
await sampleOkAsync();
expect(...).toBe(...);
});
非同期関数を実行するテストケースでは、必ずasyncをつけろ。
モック対象のモジュールや関数はテスト実行前に一旦全てimportし、その直後にjest.mockで必要なもの全てモック化するのおすすめ
原則、最初にimportされてその直後にjest.mock()でモック化されたモジュール及びその中の関数たちは、そのファイル内ではずっとモック状態になる。
例外)ただし、テストの途中でモック状態を解く関数もjestには用意されてたはず
例外は一旦無視して基本的には、可読性の観点から、ファイル内の最初にモック化したい必要なモジュール、関数、プロパティをモック化しておくと良い。
その後、テストケースに合わせて適宜モックの内容を変更するなどしたらよろし。
code: sample.test.js
// テスト対象のモジュール内関数import
import { testTargetFunc } from './testModule';
// テスト対象が依存してるモジュールで、モック化したいやつ全てimport
import { dependFuncA } from './dependA';
import { dependFuncB1, dependFuncB2 } from './dependB';
// 最初の時点でモック化しておく
jest.mock("./dependA", () => ({
dependFuncA: jest.mock()
}));
jest.mock("./dependB", () => ({
dependFuncB1: jest.mock(),
dependFuncB2: jest.mock()
}));
// テスト実行
test("sample", () => {
dependFuncA.mockimplementation(() => {...})
dependFuncB1.mockimplementation(() => {...})
dependFuncB2.mockimplementation(() => {...})
testTargetFunc();
})
モジュール直下のconstプロパティをモック化したい
モジュール直下のconstプロパティをモック化して、テスト毎に値を変えれるようにしたいなら...
参考:テストごとに Jest モックを変更する
ポイント
モジュール自体をモック化する
jest.mockでモジュールをモック化する際、__esModule: trueが必要
テストファイルにモジュール自体をimportしておく
ex: import * as config from './config';
テストケース(test, it)毎に値を変えたいなら、base.property = 的な感じで変更するといい
code: config.js
const export sample_property = true
code: sample.test.js
import * as config from '@/config';
jest.mock("@/config", () => ({
__esModule: true,
sample_property: null
}));
test("true pattern", () => {
config.sample_property = true;
...
expect(...);
})
test("false pattern", () => {
config.sample_property = false;
expect(...);
})
「スコープ外のデータはモックの値に使えない」的なエラーが発生する場合は、そのスコープ外データの変数名を'mock'から始めよ
以下のようなコードはエラーが発生する
code: sample.test.js
const sam = jest.fn();
jest.mock("./sampleModule", () => ({
sample: () => sam
});
これだと、スコープ外のデータがどーのこーのと怒られる。
これを回避するためには、スコープ外の変数名をmockから始まる名前に変えてやる。
これだけでOK
OKパターン
code: sample.test.js
const mockSam = jest.fn();
jest.mock("./sampleModule", () => ({
sample: () => mockSam
});